<!doctype html><html class="use-motion" lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1"><meta http-equiv="Cache-Control" content="no-transform"><meta http-equiv="Cache-Control" content="no-siteapp"><meta name="google-site-verification" content="0axhmy0-lA3xPbR8wPgyWlMZjwWSCfagKukdyeCQ7LU"><link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css"><link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css"><link href="/css/main.css?v=5.1.0" rel="stylesheet" type="text/css"><meta name="keywords" content="OVN,OVS,SDN,OpenvSwitch,Network"><link rel="alternate" href="/atom.xml" title="赵占旭的博客" type="application/atom+xml"><link rel="shortcut icon" type="image/x-icon" href="/favicon.ico?v=5.1.0"><meta name="description" content="前面我们介绍到openflow流表和logical流表的大致对应，今天我们从代码的角度看一下他是怎么实现的。"><meta name="keywords" content="OVN,OVS,SDN,OpenvSwitch,Network"><meta property="og:type" content="article"><meta property="og:title" content="OVN controller工作"><meta property="og:url" content="http://zhaozhanxu.com/2017/03/11/SDN/OVN/2017-03-11-ovn-controller/index.html"><meta property="og:site_name" content="赵占旭的博客"><meta property="og:description" content="前面我们介绍到openflow流表和logical流表的大致对应，今天我们从代码的角度看一下他是怎么实现的。"><meta property="og:locale" content="en"><meta property="og:updated_time" content="2017-12-11T14:31:18.941Z"><meta name="twitter:card" content="summary"><meta name="twitter:title" content="OVN controller工作"><meta name="twitter:description" content="前面我们介绍到openflow流表和logical流表的大致对应，今天我们从代码的角度看一下他是怎么实现的。"><script type="text/javascript" id="hexo.configurations">var NexT=window.NexT||{},CONFIG={root:"/",sidebar:{position:"left",display:"post",offset:342,offset_float:0},fancybox:!0,motion:!0}</script><link rel="canonical" href="http://zhaozhanxu.com/2017/03/11/SDN/OVN/2017-03-11-ovn-controller/"><title> OVN controller工作 | 赵占旭的博客</title></head><body itemscope itemtype="http://schema.org/WebPage" lang="en"><script>!function(e,a,t,c,n,g,o){e.GoogleAnalyticsObject="ga",e.ga=e.ga||function(){(e.ga.q=e.ga.q||[]).push(arguments)},e.ga.l=1*new Date,g=a.createElement("script"),o=a.getElementsByTagName("script")[0],g.async=1,g.src="//www.google-analytics.com/analytics.js",o.parentNode.insertBefore(g,o)}(window,document),ga("create","3a235f2280210fdd34cebc8c3647e5b8","auto"),ga("send","pageview")</script><script type="text/javascript">var _hmt=_hmt||[];!function(){var e=document.createElement("script");e.src="//hm.baidu.com/hm.js?UA-90327054-1";var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)}()</script><script type="text/javascript">!function(){var e=document.createElement("script");e.src="//tajs.qq.com/stats?sId=60806179";var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)}()</script><div class="container one-collumn sidebar-position-left page-post-detail"><div class="headband"></div><header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader" style="background-image:url(/images/public/home_bg.jpg)"><div class="header-cover"><div class="header-inner"><a class="site-home" href="/">赵占旭的博客</a><div class="site-meta"><div class="custom-logo-site-title"><div href="/" class="brand"><span class="logo-line-before"><i></i></span> <span class="site-title">赵占旭的博客</span><span class="logo-line-after"><i></i></span></div></div><h1 class="site-subtitle" itemprop="description">一花一世界 一叶一菩提</h1></div><div class="site-nav-toggle"> <button><span class="btn-bar"></span><span class="btn-bar"></span><span class="btn-bar"></span></button></div><nav class="site-nav"><ul id="menu" class="menu"><li class="menu-item menu-item-categories"><a href="/categories" rel="section"><i class="menu-item-icon fa fa-fw fa-th"></i><br> Categories</a></li><li class="menu-item menu-item-tags"><a href="/tags" rel="section"><i class="menu-item-icon fa fa-fw fa-tags"></i><br> Tags</a></li><li class="menu-item menu-item-archives"><a href="/archives" rel="section"><i class="menu-item-icon fa fa-fw fa-archive"></i><br> Archives</a></li><li class="menu-item menu-item-about"><a href="/about" rel="section"><i class="menu-item-icon fa fa-fw fa-user"></i><br> About</a></li><li class="menu-item menu-item-search"><a href="javascript:" ; class="popup-trigger"><i class="menu-item-icon fa fa-search fa-fw"></i><br> Search</a></li></ul><div class="site-search"><div class="popup local-search-popup"><div class="local-search-header clearfix"><span class="search-icon"><i class="fa fa-search"></i></span><span class="popup-btn-close"><i class="fa fa-times-circle"></i></span><div class="local-search-input-wrapper"> <input autocapitalize="off" autocomplete="off" autocorrect="off" placeholder="search.placeholder" spellcheck="false" type="text" id="local-search-input"></div></div><div id="local-search-result"></div></div></div></nav></div><div class="header-post"><div class="post-header"><div class="tags"> <a href="/tags/OVS/" rel="tag" title="OVS">OVS</a> <a href="/tags/Network/" rel="tag" title="Network">Network</a> <a href="/tags/SDN/" rel="tag" title="SDN">SDN</a> <a href="/tags/OVN/" rel="tag" title="OVN">OVN</a></div><h1>OVN controller工作</h1><h2 class="subtitle">Section 6. Controller怎么将Logical Flow翻译为Openflow</h2><div class="post-time"> <span class="post-meta-item-text">Posted on</span> <time itemprop="dateCreated" datetime="2017-03-11T00:00:00+08:00" content="2017-03-11" title="2017-03-11 00:00:00">2017-03-11</time></div></div></div></div></header><main id="main" class="main"><div class="main-inner"><div class="content-wrap"><div id="content" class="content"><div id="posts" class="posts-expand"><article class="post post-type-normal" itemscope itemtype="http://schema.org/Article"><link itemprop="mainEntityOfPage" href="http://zhaozhanxu.com/2017/03/11/SDN/OVN/2017-03-11-ovn-controller/"><span style="display:none" itemprop="author" itemscope itemtype="http://schema.org/Person"><meta itemprop="name" content="赵占旭"><meta itemprop="description" content=""><meta itemprop="image" content="/images/public/me.jpg"></span><span style="display:none" itemprop="publisher" itemscope itemtype="http://schema.org/Organization"><meta itemprop="name" content="赵占旭的博客"> <span style="display:none" itemprop="logo" itemscope itemtype="http://schema.org/ImageObject"><img style="display:none" itemprop="url image" alt="赵占旭的博客" src=""></span></span><div class="post-inner"><header class="post-header"><h2 class="post-title" itemprop="name headline"> OVN controller工作</h2><div class="post-meta"><span class="post-time"><span class="post-meta-item-icon"><i class="fa fa-calendar-o"></i></span> <span class="post-meta-item-text">Posted on</span> <time title="Post created" itemprop="dateCreated datePublished" datetime="2017-03-11T00:00:00+08:00">2017-03-11</time></span></div></header><div class="post-info"><div class="post-categories"> <a class="color" href="/categories/OVN/" rel="tag">OVN</a></div><div class="post-tags"> <a class="color" href="/tags/OVS/" rel="tag">OVS</a> <a class="color" href="/tags/Network/" rel="tag">Network</a> <a class="color" href="/tags/SDN/" rel="tag">SDN</a> <a class="color" href="/tags/OVN/" rel="tag">OVN</a></div><div class="clearfix"></div></div><div class="post-body" itemprop="articleBody"><p>前面我们介绍到openflow流表和logical流表的大致对应，今天我们从代码的角度看一下他是怎么实现的。</p><a id="more"></a><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span></span><br><span class="line">main(<span class="keyword">int</span> argc, <span class="keyword">char</span> *argv[])</span><br><span class="line">&#123;</span><br><span class="line">    <span class="comment">//为LB初始化group id</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">group_table</span> <span class="title">group_table</span>;</span></span><br><span class="line">    group_table.group_ids = bitmap_allocate(MAX_OVN_GROUPS);</span><br><span class="line">    bitmap_set1(group_table.group_ids, <span class="number">0</span>); <span class="comment">/* Group id 0 is invalid. */</span></span><br><span class="line">    hmap_init(&amp;group_table.desired_groups);</span><br><span class="line">    hmap_init(&amp;group_table.existing_groups);</span><br><span class="line"></span><br><span class="line">    <span class="comment">//连接ovs的ovsdb实例，我们不监控所有的表，所以模块必须注册感兴趣的部分</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">ovsdb_idl_loop</span> <span class="title">ovs_idl_loop</span> = <span class="title">OVSDB_IDL_LOOP_INITIALIZER</span>(</span></span><br><span class="line"><span class="class">        <span class="title">ovsdb_idl_create</span>(<span class="title">ovs_remote</span>, &amp;<span class="title">ovsrec_idl_class</span>, <span class="title">false</span>, <span class="title">true</span>));</span></span><br><span class="line">    ovsdb_idl_add_table(ovs_idl_loop.idl, &amp;ovsrec_table_open_vswitch);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl,</span><br><span class="line">                         &amp;ovsrec_open_vswitch_col_external_ids);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_open_vswitch_col_bridges);</span><br><span class="line">    ovsdb_idl_add_table(ovs_idl_loop.idl, &amp;ovsrec_table_interface);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_interface_col_name);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_interface_col_type);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_interface_col_options);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_interface_col_ofport);</span><br><span class="line">    ovsdb_idl_add_table(ovs_idl_loop.idl, &amp;ovsrec_table_port);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_port_col_name);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_port_col_interfaces);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_port_col_external_ids);</span><br><span class="line">    ovsdb_idl_add_table(ovs_idl_loop.idl, &amp;ovsrec_table_bridge);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_bridge_col_ports);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_bridge_col_name);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_bridge_col_fail_mode);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_bridge_col_other_config);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_bridge_col_external_ids);</span><br><span class="line">    <span class="comment">//chassis_register_ovs_idl</span></span><br><span class="line">    ovsdb_idl_add_table(ovs_idl_loop.idl, &amp;ovsrec_table_open_vswitch);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_open_vswitch_col_external_ids);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_open_vswitch_col_iface_types);</span><br><span class="line">    ovsdb_idl_add_table(ovs_idl_loop.idl, &amp;ovsrec_table_bridge);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_bridge_col_datapath_type);</span><br><span class="line">    <span class="comment">//encaps_register_ovs_idl</span></span><br><span class="line">    ovsdb_idl_add_table(ovs_idl_loop.idl, &amp;ovsrec_table_bridge);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_bridge_col_ports);</span><br><span class="line">    ovsdb_idl_add_table(ovs_idl_loop.idl, &amp;ovsrec_table_port);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_port_col_name);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_port_col_interfaces);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_port_col_external_ids);</span><br><span class="line">    ovsdb_idl_add_table(ovs_idl_loop.idl, &amp;ovsrec_table_interface);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_interface_col_name);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_interface_col_type);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_interface_col_options);</span><br><span class="line">    <span class="comment">//binding_register_ovs_idl</span></span><br><span class="line">    ovsdb_idl_add_table(ovs_idl_loop.idl, &amp;ovsrec_table_open_vswitch);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_open_vswitch_col_bridges);</span><br><span class="line">    ovsdb_idl_add_table(ovs_idl_loop.idl, &amp;ovsrec_table_bridge);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_bridge_col_name);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_bridge_col_ports);</span><br><span class="line">    ovsdb_idl_add_table(ovs_idl_loop.idl, &amp;ovsrec_table_port);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_port_col_name);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_port_col_interfaces);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_port_col_qos);</span><br><span class="line">    ovsdb_idl_add_table(ovs_idl_loop.idl, &amp;ovsrec_table_interface);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_interface_col_name);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_interface_col_external_ids);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_interface_col_status);</span><br><span class="line">    ovsdb_idl_add_table(ovs_idl_loop.idl, &amp;ovsrec_table_qos);</span><br><span class="line">    <span class="comment">//physical_register_ovs_idl</span></span><br><span class="line">    ovsdb_idl_add_table(ovs_idl_loop.idl, &amp;ovsrec_table_bridge);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_bridge_col_ports);</span><br><span class="line">    ovsdb_idl_add_table(ovs_idl_loop.idl, &amp;ovsrec_table_port);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_port_col_name);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_port_col_interfaces);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_port_col_external_ids);</span><br><span class="line">    ovsdb_idl_add_table(ovs_idl_loop.idl, &amp;ovsrec_table_interface);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_interface_col_name);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_interface_col_ofport);</span><br><span class="line">    ovsdb_idl_add_column(ovs_idl_loop.idl, &amp;ovsrec_interface_col_external_ids);</span><br><span class="line">    <span class="comment">//确保成功连接到ovs的ovsdb，并且取回上面设置的内容</span></span><br><span class="line">    ovsdb_idl_get_initial_snapshot(ovs_idl_loop.idl);</span><br><span class="line"></span><br><span class="line">    <span class="comment">//连接控制节点的sbdb，监听表的所有内容，除了下面忽略的nb_cfg</span></span><br><span class="line">    <span class="comment">//确保成功连接，并且取回相关的内容</span></span><br><span class="line">    <span class="keyword">char</span> *ovnsb_remote = get_ovnsb_remote(ovs_idl_loop.idl);</span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">ovsdb_idl_loop</span> <span class="title">ovnsb_idl_loop</span> = <span class="title">OVSDB_IDL_LOOP_INITIALIZER</span>(</span></span><br><span class="line"><span class="class">        <span class="title">ovsdb_idl_create</span>(<span class="title">ovnsb_remote</span>, &amp;<span class="title">sbrec_idl_class</span>, <span class="title">true</span>, <span class="title">true</span>));</span></span><br><span class="line">    ovsdb_idl_omit_alert(ovnsb_idl_loop.idl, &amp;sbrec_chassis_col_nb_cfg);</span><br><span class="line">    update_sb_monitors(ovnsb_idl_loop.idl, <span class="literal">NULL</span>, <span class="literal">NULL</span>, <span class="literal">NULL</span>);</span><br><span class="line">    ovsdb_idl_get_initial_snapshot(ovnsb_idl_loop.idl);</span><br><span class="line"></span><br><span class="line">    <span class="comment">//初始化conntrack zone</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">simap</span> <span class="title">ct_zones</span> = <span class="title">SIMAP_INITIALIZER</span>(&amp;<span class="title">ct_zones</span>);</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">shash</span> <span class="title">pending_ct_zones</span> = <span class="title">SHASH_INITIALIZER</span>(&amp;<span class="title">pending_ct_zones</span>);</span></span><br><span class="line">    <span class="keyword">unsigned</span> <span class="keyword">long</span> ct_zone_bitmap[BITMAP_N_LONGS(MAX_CT_ZONES)];</span><br><span class="line">    <span class="built_in">memset</span>(ct_zone_bitmap, <span class="number">0</span>, <span class="keyword">sizeof</span> ct_zone_bitmap);</span><br><span class="line">    <span class="comment">//默认是zone 0</span></span><br><span class="line">    bitmap_set1(ct_zone_bitmap, <span class="number">0</span>);</span><br><span class="line">    restore_ct_zones(ovs_idl_loop.idl, &amp;ct_zones, ct_zone_bitmap);</span><br><span class="line">    unixctl_command_register(<span class="string">"ct-zone-list"</span>, <span class="string">""</span>, <span class="number">0</span>, <span class="number">0</span>,</span><br><span class="line">                             ct_zone_list, &amp;ct_zones);</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">pending_pkt</span> <span class="title">pending_pkt</span> = &#123;</span> .conn = <span class="literal">NULL</span> &#125;;</span><br><span class="line">    unixctl_command_register(<span class="string">"inject-pkt"</span>, <span class="string">"MICROFLOW"</span>, <span class="number">1</span>, <span class="number">1</span>, inject_pkt,</span><br><span class="line">                             &amp;pending_pkt);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">while</span> (!exiting) &#123;</span><br><span class="line">        <span class="comment">//检测sbdb是否变化</span></span><br><span class="line">        <span class="keyword">char</span> *new_ovnsb_remote = get_ovnsb_remote(ovs_idl_loop.idl);</span><br><span class="line">        <span class="keyword">if</span> (<span class="built_in">strcmp</span>(ovnsb_remote, new_ovnsb_remote)) &#123;</span><br><span class="line">            <span class="built_in">free</span>(ovnsb_remote);</span><br><span class="line">            ovnsb_remote = new_ovnsb_remote;</span><br><span class="line">            ovsdb_idl_set_remote(ovnsb_idl_loop.idl, ovnsb_remote, <span class="literal">true</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="built_in">free</span>(new_ovnsb_remote);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="class"><span class="keyword">struct</span> <span class="title">controller_ctx</span> <span class="title">ctx</span> = &#123;</span></span><br><span class="line">            .ovs_idl = ovs_idl_loop.idl,</span><br><span class="line">            .ovs_idl_txn = ovsdb_idl_loop_run(&amp;ovs_idl_loop),</span><br><span class="line">            .ovnsb_idl = ovnsb_idl_loop.idl,</span><br><span class="line">            .ovnsb_idl_txn = ovsdb_idl_loop_run(&amp;ovnsb_idl_loop),</span><br><span class="line">        &#125;;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//默认5s的探测sbdb</span></span><br><span class="line">        update_probe_interval(&amp;ctx);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//包含了struct local_datapath节点</span></span><br><span class="line">        <span class="class"><span class="keyword">struct</span> <span class="title">hmap</span> <span class="title">local_datapaths</span> = <span class="title">HMAP_INITIALIZER</span>(&amp;<span class="title">local_datapaths</span>);</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">//包含了驻留在本地的所有逻辑端口的名字。</span></span><br><span class="line">        <span class="comment">//这些逻辑端口包括虚拟机的虚拟端口、</span></span><br><span class="line">        <span class="comment">//l2gateway-chassis指派的l2网关端口以及localnet端口</span></span><br><span class="line">        <span class="class"><span class="keyword">struct</span> <span class="title">sset</span> <span class="title">local_lports</span> = <span class="title">SSET_INITIALIZER</span>(&amp;<span class="title">local_lports</span>);</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">//获取br-int，如果没有则创建，名字不一定是br-int</span></span><br><span class="line">        <span class="keyword">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">ovsrec_bridge</span> *<span class="title">br_int</span> = <span class="title">get_br_int</span>(&amp;<span class="title">ctx</span>);</span></span><br><span class="line">        <span class="comment">//获取本地ovs的system-id</span></span><br><span class="line">        <span class="keyword">const</span> <span class="keyword">char</span> *chassis_id = get_chassis_id(ctx.ovs_idl);</span><br><span class="line"></span><br><span class="line">        <span class="class"><span class="keyword">struct</span> <span class="title">ldatapath_index</span> <span class="title">ldatapaths</span>;</span></span><br><span class="line">        <span class="class"><span class="keyword">struct</span> <span class="title">lport_index</span> <span class="title">lports</span>;</span></span><br><span class="line">        <span class="class"><span class="keyword">struct</span> <span class="title">mcgroup_index</span> <span class="title">mcgroups</span>;</span></span><br><span class="line">        ldatapath_index_init(&amp;ldatapaths, ctx.ovnsb_idl);</span><br><span class="line">        lport_index_init(&amp;lports, ctx.ovnsb_idl);</span><br><span class="line">        mcgroup_index_init(&amp;mcgroups, ctx.ovnsb_idl);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">sbrec_chassis</span> *<span class="title">chassis</span> = <span class="title">NULL</span>;</span></span><br><span class="line">        <span class="keyword">if</span> (chassis_id) &#123;</span><br><span class="line">            <span class="comment">//根据本地的system-id，获取本地encap type和IP、hostname</span></span><br><span class="line">            <span class="comment">//datapath type、端口type并且更新到ovn的chassis中</span></span><br><span class="line">            <span class="comment">//查看ovn的chassis方法为ovn-sbctl list Chassis</span></span><br><span class="line">            chassis = chassis_run(&amp;ctx, chassis_id, br_int);</span><br><span class="line">            <span class="comment">//根据ovn配置的创建tunnel信息</span></span><br><span class="line">            <span class="comment">//找到需要和其他chassis建立tunnel的隧道信息，并且创建隧道</span></span><br><span class="line">            <span class="comment">//所谓的创建，其实就是给ovs的数据库插入端口信息</span></span><br><span class="line">            encaps_run(&amp;ctx, br_int, chassis_id);</span><br><span class="line">            <span class="comment">//首先获取端口的信息，本地端口获取external-ids的iface-id</span></span><br><span class="line">            <span class="comment">//egress端口获取options的remote_ip，查看命令为ovs-vsctl list interface</span></span><br><span class="line">            <span class="comment">//将上面获取的iface-id填充到sbdb的port_binding的logical_port中</span></span><br><span class="line">            <span class="comment">//给egress端口设置qos，因为ovn现在给vm的出口配置qos最终会通过queue配置到出口</span></span><br><span class="line">            binding_run(&amp;ctx, br_int, chassis, &amp;ldatapaths, &amp;lports,</span><br><span class="line">                        &amp;local_datapaths, &amp;local_lports);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (br_int &amp;&amp; chassis) &#123;</span><br><span class="line">            <span class="class"><span class="keyword">struct</span> <span class="title">shash</span> <span class="title">addr_sets</span> = <span class="title">SHASH_INITIALIZER</span>(&amp;<span class="title">addr_sets</span>);</span></span><br><span class="line">            addr_sets_init(&amp;ctx, &amp;addr_sets);</span><br><span class="line"></span><br><span class="line">            <span class="comment">//这块没找到相关信息，据我所知ovs2.6还有patch port</span></span><br><span class="line">            <span class="comment">//ovs2.7开始就没有patch port了，都是通过流表resubmit重新从表16开始匹配</span></span><br><span class="line">            patch_run(&amp;ctx, br_int, chassis, &amp;local_datapaths);</span><br><span class="line"></span><br><span class="line">            <span class="keyword">enum</span> mf_field_id mff_ovn_geneve = ofctrl_run(br_int,</span><br><span class="line">                                                         &amp;pending_ct_zones);</span><br><span class="line"></span><br><span class="line">            pinctrl_run(&amp;ctx, &amp;lports, br_int, chassis, &amp;local_datapaths);</span><br><span class="line">            update_ct_zones(&amp;local_lports, &amp;local_datapaths, &amp;ct_zones,</span><br><span class="line">                            ct_zone_bitmap, &amp;pending_ct_zones);</span><br><span class="line">            <span class="keyword">if</span> (ctx.ovs_idl_txn) &#123;</span><br><span class="line"></span><br><span class="line">                <span class="comment">//设置ct_zone，通过命令ovs-vsctl list Bridge可以查看</span></span><br><span class="line">                commit_ct_zones(br_int, &amp;pending_ct_zones);</span><br><span class="line"></span><br><span class="line">                <span class="class"><span class="keyword">struct</span> <span class="title">hmap</span> <span class="title">flow_table</span> = <span class="title">HMAP_INITIALIZER</span>(&amp;<span class="title">flow_table</span>);</span></span><br><span class="line">                <span class="comment">//此处是生成逻辑流表的地方，这里不多说，下面详说</span></span><br><span class="line">                lflow_run(&amp;ctx, chassis, &amp;lports, &amp;mcgroups,</span><br><span class="line">                          &amp;local_datapaths, &amp;group_table, &amp;ct_zones,</span><br><span class="line">                          &amp;addr_sets, &amp;flow_table);</span><br><span class="line"></span><br><span class="line">                <span class="comment">//一些和物理设备相关和逻辑流表无关的，下面也会细看</span></span><br><span class="line">                physical_run(&amp;ctx, mff_ovn_geneve,</span><br><span class="line">                             br_int, chassis, &amp;ct_zones, &amp;lports,</span><br><span class="line">                             &amp;flow_table, &amp;local_datapaths);</span><br><span class="line"></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>lflow_run</code>主要有两块的工作，一个是翻译逻辑流表的函数<code>add_logical_flows--&gt;consider_logical_flow</code>，另外一个是添加邻居子系统相关流表的函数<code>add_neighbor_flows--&gt;consider_neighbor_flow</code>。</p><ul><li>逻辑流表翻译是ingress table 0-15对应openflow的table 16-31，egress table 0-15 对应openflow的table 48-63</li><li>邻居子系统相关的流表是对应openflow的table 66</li></ul><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">static</span> <span class="keyword">void</span></span><br><span class="line">consider_logical_flow(<span class="keyword">const</span> struct lport_index *lports,</span><br><span class="line">                      <span class="keyword">const</span> struct mcgroup_index *mcgroups,</span><br><span class="line">                      <span class="keyword">const</span> struct sbrec_logical_flow *lflow,</span><br><span class="line">                      <span class="keyword">const</span> struct hmap *local_datapaths,</span><br><span class="line">                      struct group_table *group_table,</span><br><span class="line">                      <span class="keyword">const</span> struct simap *ct_zones,</span><br><span class="line">                      <span class="keyword">const</span> struct sbrec_chassis *chassis,</span><br><span class="line">                      struct hmap *dhcp_opts,</span><br><span class="line">                      struct hmap *dhcpv6_opts,</span><br><span class="line">                      <span class="keyword">uint32_t</span> *conj_id_ofs,</span><br><span class="line">                      <span class="keyword">const</span> struct shash *addr_sets,</span><br><span class="line">                      struct hmap *flow_table)</span><br><span class="line">&#123;</span><br><span class="line">    <span class="comment">//判定逻辑流表是ingress还是egress</span></span><br><span class="line">    <span class="keyword">bool</span> ingress = !<span class="built_in">strcmp</span>(lflow-&gt;pipeline, <span class="string">"ingress"</span>);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">sbrec_datapath_binding</span> *<span class="title">ldp</span> = <span class="title">lflow</span>-&gt;<span class="title">logical_datapath</span>;</span></span><br><span class="line">    <span class="keyword">if</span> (!get_local_datapath(local_datapaths, ldp-&gt;tunnel_key)) &#123;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//逻辑流表的ID和openflow流表ID的对应关系，ingress从表16开始，egress从48开始</span></span><br><span class="line">    <span class="keyword">uint8_t</span> first_ptable = (ingress</span><br><span class="line">                            ? OFTABLE_LOG_INGRESS_PIPELINE</span><br><span class="line">                            : OFTABLE_LOG_EGRESS_PIPELINE);</span><br><span class="line">    <span class="keyword">uint8_t</span> ptable = first_ptable + lflow-&gt;table_id;</span><br><span class="line">    <span class="comment">//这块可能是关于发送口的流表，ingress从表32开始，egress从64开始</span></span><br><span class="line">    <span class="keyword">uint8_t</span> output_ptable = (ingress</span><br><span class="line">                             ? OFTABLE_REMOTE_OUTPUT</span><br><span class="line">                             : OFTABLE_SAVE_INPORT);</span><br><span class="line"></span><br><span class="line">    <span class="comment">//此处开始解析逻辑流表的action到openflow流表的action</span></span><br><span class="line">    <span class="keyword">uint64_t</span> ovnacts_stub[<span class="number">1024</span> / <span class="number">8</span>];</span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">ofpbuf</span> <span class="title">ovnacts</span> = <span class="title">OFPBUF_STUB_INITIALIZER</span>(<span class="title">ovnacts_stub</span>);</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">ovnact_parse_params</span> <span class="title">pp</span> = &#123;</span></span><br><span class="line">        .symtab = &amp;symtab,</span><br><span class="line">        .dhcp_opts = dhcp_opts,</span><br><span class="line">        .dhcpv6_opts = dhcpv6_opts,</span><br><span class="line"></span><br><span class="line">        .pipeline = ingress ? OVNACT_P_INGRESS : OVNACT_P_EGRESS,</span><br><span class="line">        .n_tables = LOG_PIPELINE_LEN,</span><br><span class="line">        .cur_ltable = lflow-&gt;table_id,</span><br><span class="line">    &#125;;</span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">expr</span> *<span class="title">prereqs</span>;</span></span><br><span class="line">    <span class="keyword">char</span> *error;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//新加的，没看懂，说是用local info替换lflow-&gt;actions.....</span></span><br><span class="line">    <span class="keyword">const</span> <span class="keyword">char</span> *new_actions = (<span class="keyword">const</span> <span class="keyword">char</span> *)replace_local_info(lflow-&gt;actions, chassis);</span><br><span class="line"></span><br><span class="line">    <span class="comment">//详细的解析action不说了，可以查看函数parse_action</span></span><br><span class="line">    error = ovnacts_parse_string(new_actions, &amp;pp, &amp;ovnacts, &amp;prereqs);</span><br><span class="line">    <span class="keyword">if</span> (error) &#123;</span><br><span class="line">        <span class="keyword">static</span> <span class="class"><span class="keyword">struct</span> <span class="title">vlog_rate_limit</span> <span class="title">rl</span> = <span class="title">VLOG_RATE_LIMIT_INIT</span>(1, 1);</span></span><br><span class="line">        VLOG_WARN_RL(&amp;rl, <span class="string">"error parsing actions \"%s\": %s"</span>,</span><br><span class="line">                     lflow-&gt;actions, error);</span><br><span class="line">        <span class="built_in">free</span>(error);</span><br><span class="line">        ovnacts_free(ovnacts.data, ovnacts.size);</span><br><span class="line">        ofpbuf_uninit(&amp;ovnacts);</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//将之前解析的action转换成openflow的action</span></span><br><span class="line">    <span class="keyword">uint64_t</span> ofpacts_stub[<span class="number">1024</span> / <span class="number">8</span>];</span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">ofpbuf</span> <span class="title">ofpacts</span> = <span class="title">OFPBUF_STUB_INITIALIZER</span>(<span class="title">ofpacts_stub</span>);</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">lookup_port_aux</span> <span class="title">aux</span> = &#123;</span></span><br><span class="line">        .lports = lports,</span><br><span class="line">        .mcgroups = mcgroups,</span><br><span class="line">        .dp = lflow-&gt;logical_datapath</span><br><span class="line">    &#125;;</span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">ovnact_encode_params</span> <span class="title">ep</span> = &#123;</span></span><br><span class="line">        .lookup_port = lookup_port_cb,</span><br><span class="line">        .aux = &amp;aux,</span><br><span class="line">        .is_switch = is_switch(ldp),</span><br><span class="line">        .is_gateway_router = is_gateway_router(ldp, local_datapaths),</span><br><span class="line">        .ct_zones = ct_zones,</span><br><span class="line">        .group_table = group_table,</span><br><span class="line"></span><br><span class="line">        .pipeline = ingress ? OVNACT_P_INGRESS : OVNACT_P_EGRESS,</span><br><span class="line">        .ingress_ptable = OFTABLE_LOG_INGRESS_PIPELINE,</span><br><span class="line">        .egress_ptable = OFTABLE_LOG_EGRESS_PIPELINE,</span><br><span class="line">        .output_ptable = output_ptable,</span><br><span class="line">        .mac_bind_ptable = OFTABLE_MAC_BINDING,</span><br><span class="line">    &#125;;</span><br><span class="line">    <span class="comment">//每个action都有一个对应的两个函数进行转换，不细看了</span></span><br><span class="line">    ovnacts_encode(ovnacts.data, ovnacts.size, &amp;ep, &amp;ofpacts);</span><br><span class="line">    ovnacts_free(ovnacts.data, ovnacts.size);</span><br><span class="line">    ofpbuf_uninit(&amp;ovnacts);</span><br><span class="line"></span><br><span class="line">    <span class="comment">//将ovn的match信息翻译为openflow的match</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">hmap</span> <span class="title">matches</span>;</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">expr</span> *<span class="title">expr</span>;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">//同上不造什么鬼</span></span><br><span class="line">    <span class="keyword">const</span> <span class="keyword">char</span> *new_match = (<span class="keyword">const</span> <span class="keyword">char</span> *)replace_local_info(lflow-&gt;match, chassis);</span><br><span class="line"></span><br><span class="line">    <span class="comment">//解析匹配项，将字符串解析为宏定义，比如&amp;解析成LEX_T_LOG_AND</span></span><br><span class="line">    expr = expr_parse_string(new_match, &amp;symtab, addr_sets, &amp;error);</span><br><span class="line">    <span class="keyword">if</span> (!error) &#123;</span><br><span class="line">        <span class="keyword">if</span> (prereqs) &#123;</span><br><span class="line">            expr = expr_combine(EXPR_T_AND, expr, prereqs);</span><br><span class="line">            prereqs = <span class="literal">NULL</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        expr = expr_annotate(expr, &amp;symtab, &amp;error);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (error) &#123;</span><br><span class="line">        <span class="keyword">static</span> <span class="class"><span class="keyword">struct</span> <span class="title">vlog_rate_limit</span> <span class="title">rl</span> = <span class="title">VLOG_RATE_LIMIT_INIT</span>(1, 1);</span></span><br><span class="line">        VLOG_WARN_RL(&amp;rl, <span class="string">"error parsing match \"%s\": %s"</span>,</span><br><span class="line">                     lflow-&gt;match, error);</span><br><span class="line">        expr_destroy(prereqs);</span><br><span class="line">        ofpbuf_uninit(&amp;ofpacts);</span><br><span class="line">        <span class="built_in">free</span>(error);</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">condition_aux</span> <span class="title">cond_aux</span> = &#123;</span> lports, chassis &#125;;</span><br><span class="line">    expr = expr_simplify(expr, is_chassis_resident_cb, &amp;cond_aux);</span><br><span class="line">    expr = expr_normalize(expr);</span><br><span class="line">    <span class="comment">//表达式转换成到matches</span></span><br><span class="line">    <span class="keyword">uint32_t</span> n_conjs = expr_to_matches(expr, lookup_port_cb, &amp;aux,</span><br><span class="line">                                       &amp;matches);</span><br><span class="line">    expr_destroy(expr);</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">expr_match</span> *<span class="title">m</span>;</span></span><br><span class="line">    HMAP_FOR_EACH (m, hmap_node, &amp;matches) &#123;</span><br><span class="line">        match_set_metadata(&amp;m-&gt;match,</span><br><span class="line">                           htonll(lflow-&gt;logical_datapath-&gt;tunnel_key));</span><br><span class="line">        <span class="keyword">if</span> (m-&gt;match.wc.masks.conj_id) &#123;</span><br><span class="line">            m-&gt;match.flow.conj_id += *conj_id_ofs;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (!m-&gt;n) &#123;</span><br><span class="line">            <span class="comment">//生成openflow流表</span></span><br><span class="line">            ofctrl_add_flow(flow_table, ptable, lflow-&gt;priority,</span><br><span class="line">                            lflow-&gt;header_.uuid.parts[<span class="number">0</span>], &amp;m-&gt;match, &amp;ofpacts);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="keyword">uint64_t</span> conj_stubs[<span class="number">64</span> / <span class="number">8</span>];</span><br><span class="line">            <span class="class"><span class="keyword">struct</span> <span class="title">ofpbuf</span> <span class="title">conj</span>;</span></span><br><span class="line"></span><br><span class="line">            ofpbuf_use_stub(&amp;conj, conj_stubs, <span class="keyword">sizeof</span> conj_stubs);</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; m-&gt;n; i++) &#123;</span><br><span class="line">                <span class="keyword">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">cls_conjunction</span> *<span class="title">src</span> = &amp;<span class="title">m</span>-&gt;<span class="title">conjunctions</span>[<span class="title">i</span>];</span></span><br><span class="line">                <span class="class"><span class="keyword">struct</span> <span class="title">ofpact_conjunction</span> *<span class="title">dst</span>;</span></span><br><span class="line"></span><br><span class="line">                dst = ofpact_put_CONJUNCTION(&amp;conj);</span><br><span class="line">                dst-&gt;id = src-&gt;id + *conj_id_ofs;</span><br><span class="line">                dst-&gt;clause = src-&gt;clause;</span><br><span class="line">                dst-&gt;n_clauses = src-&gt;n_clauses;</span><br><span class="line">            &#125;</span><br><span class="line">            ofctrl_add_flow(flow_table, ptable, lflow-&gt;priority, <span class="number">0</span>, &amp;m-&gt;match,</span><br><span class="line">                            &amp;conj);</span><br><span class="line">            ofpbuf_uninit(&amp;conj);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">static</span> <span class="keyword">void</span></span><br><span class="line">consider_neighbor_flow(<span class="keyword">const</span> struct lport_index *lports,</span><br><span class="line">                       <span class="keyword">const</span> struct sbrec_mac_binding *b,</span><br><span class="line">                       struct hmap *flow_table)</span><br><span class="line">&#123;</span><br><span class="line">    <span class="comment">//通过MAC_Binding查找到Port_Binding</span></span><br><span class="line">    <span class="keyword">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">sbrec_port_binding</span> *<span class="title">pb</span></span></span><br><span class="line"><span class="class">        = <span class="title">lport_lookup_by_name</span>(<span class="title">lports</span>, <span class="title">b</span>-&gt;<span class="title">logical_port</span>);</span></span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">eth_addr</span> <span class="title">mac</span>;</span></span><br><span class="line">    <span class="comment">//解析mac</span></span><br><span class="line">    eth_addr_from_string(b-&gt;mac, &amp;mac);</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">match</span> <span class="title">match</span> = <span class="title">MATCH_CATCHALL_INITIALIZER</span>;</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="built_in">strchr</span>(b-&gt;ip, <span class="string">'.'</span>)) &#123;</span><br><span class="line">        ovs_be32 ip;</span><br><span class="line">        <span class="comment">//解析IP</span></span><br><span class="line">        ip_parse(b-&gt;ip, &amp;ip);</span><br><span class="line">        <span class="comment">//然后match中reg0匹配IP</span></span><br><span class="line">        match_set_reg(&amp;match, <span class="number">0</span>, ntohl(ip));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">uint64_t</span> stub[<span class="number">1024</span> / <span class="number">8</span>];</span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">ofpbuf</span> <span class="title">ofpacts</span> = <span class="title">OFPBUF_STUB_INITIALIZER</span>(<span class="title">stub</span>);</span></span><br><span class="line">    <span class="comment">//设置action是修改目的MAC</span></span><br><span class="line">    put_load(mac.ea, <span class="keyword">sizeof</span> mac.ea, MFF_ETH_DST, <span class="number">0</span>, <span class="number">48</span>, &amp;ofpacts);</span><br><span class="line">    <span class="comment">//添加流表</span></span><br><span class="line">    ofctrl_add_flow(flow_table, OFTABLE_MAC_BINDING, <span class="number">100</span>, <span class="number">0</span>, &amp;match, &amp;ofpacts);</span><br><span class="line">    ofpbuf_uninit(&amp;ofpacts);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>physical_run</code></p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">void</span></span><br><span class="line">physical_run(struct controller_ctx *ctx, <span class="keyword">enum</span> mf_field_id mff_ovn_geneve,</span><br><span class="line">             <span class="keyword">const</span> struct ovsrec_bridge *br_int,</span><br><span class="line">             <span class="keyword">const</span> struct sbrec_chassis *chassis,</span><br><span class="line">             <span class="keyword">const</span> struct simap *ct_zones, struct lport_index *lports,</span><br><span class="line">             struct hmap *flow_table, struct hmap *local_datapaths)</span><br><span class="line">&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">bool</span> physical_map_changed = <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">simap</span> <span class="title">new_localvif_to_ofport</span> =</span></span><br><span class="line"><span class="class">        <span class="title">SIMAP_INITIALIZER</span>(&amp;<span class="title">new_localvif_to_ofport</span>);</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">simap</span> <span class="title">new_tunnel_to_ofport</span> =</span></span><br><span class="line"><span class="class">        <span class="title">SIMAP_INITIALIZER</span>(&amp;<span class="title">new_tunnel_to_ofport</span>);</span></span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; br_int-&gt;n_ports; i++) &#123;</span><br><span class="line">        <span class="keyword">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">ovsrec_port</span> *<span class="title">port_rec</span> = <span class="title">br_int</span>-&gt;<span class="title">ports</span>[<span class="title">i</span>];</span></span><br><span class="line">        <span class="comment">//对应的数据查看用ovs-vsctl list port</span></span><br><span class="line">        <span class="keyword">const</span> <span class="keyword">char</span> *chassis_id = smap_get(&amp;port_rec-&gt;external_ids,</span><br><span class="line">                                          <span class="string">"ovn-chassis-id"</span>);</span><br><span class="line">        <span class="keyword">const</span> <span class="keyword">char</span> *localnet = smap_get(&amp;port_rec-&gt;external_ids,</span><br><span class="line">                                        <span class="string">"ovn-localnet-port"</span>);</span><br><span class="line">        <span class="keyword">const</span> <span class="keyword">char</span> *l2gateway = smap_get(&amp;port_rec-&gt;external_ids,</span><br><span class="line">                                        <span class="string">"ovn-l2gateway-port"</span>);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>; j &lt; port_rec-&gt;n_interfaces; j++) &#123;</span><br><span class="line">            <span class="keyword">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">ovsrec_interface</span> *<span class="title">iface_rec</span> = <span class="title">port_rec</span>-&gt;<span class="title">interfaces</span>[<span class="title">j</span>];</span></span><br><span class="line">            <span class="comment">//查看信息用ovs-vsctl list interface</span></span><br><span class="line">            <span class="keyword">int64_t</span> ofport = iface_rec-&gt;ofport[<span class="number">0</span>];</span><br><span class="line"></span><br><span class="line">            <span class="comment">/* Record as patch to local net, logical patch port, chassis, or</span></span><br><span class="line"><span class="comment">             * local logical port. */</span></span><br><span class="line">            <span class="keyword">bool</span> is_patch = !<span class="built_in">strcmp</span>(iface_rec-&gt;type, <span class="string">"patch"</span>);</span><br><span class="line">            <span class="comment">//localnet patch ports和L2 gateway patch ports都当做VIF处理</span></span><br><span class="line">            <span class="keyword">if</span> (is_patch &amp;&amp; localnet) &#123;</span><br><span class="line">                simap_put(&amp;new_localvif_to_ofport, localnet, ofport);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (is_patch &amp;&amp; l2gateway) &#123;</span><br><span class="line">                simap_put(&amp;new_localvif_to_ofport, l2gateway, ofport);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="comment">//有chassis_id表示是连接到某个宿主机的tunnel口</span></span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (chassis_id) &#123;</span><br><span class="line">                <span class="keyword">enum</span> chassis_tunnel_type tunnel_type;</span><br><span class="line">                <span class="keyword">if</span> (!<span class="built_in">strcmp</span>(iface_rec-&gt;type, <span class="string">"geneve"</span>)) &#123;</span><br><span class="line">                    tunnel_type = GENEVE;</span><br><span class="line">                    <span class="keyword">if</span> (!mff_ovn_geneve) &#123;</span><br><span class="line">                        <span class="keyword">continue</span>;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125; <span class="keyword">else</span> <span class="keyword">if</span> (!<span class="built_in">strcmp</span>(iface_rec-&gt;type, <span class="string">"stt"</span>)) &#123;</span><br><span class="line">                    tunnel_type = STT;</span><br><span class="line">                &#125; <span class="keyword">else</span> <span class="keyword">if</span> (!<span class="built_in">strcmp</span>(iface_rec-&gt;type, <span class="string">"vxlan"</span>)) &#123;</span><br><span class="line">                    tunnel_type = VXLAN;</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    <span class="keyword">continue</span>;</span><br><span class="line">                &#125;</span><br><span class="line"></span><br><span class="line">                <span class="comment">//找到chassis_id对应的tunnel口，存在即更新，不存在创建</span></span><br><span class="line">                simap_put(&amp;new_tunnel_to_ofport, chassis_id, ofport);</span><br><span class="line">                <span class="class"><span class="keyword">struct</span> <span class="title">chassis_tunnel</span> *<span class="title">tun</span> = <span class="title">chassis_tunnel_find</span>(<span class="title">chassis_id</span>);</span></span><br><span class="line">                <span class="keyword">if</span> (tun) &#123;</span><br><span class="line">                    <span class="keyword">if</span> (tun-&gt;ofport != u16_to_ofp(ofport) ||</span><br><span class="line">                        tun-&gt;type != tunnel_type) &#123;</span><br><span class="line">                        tun-&gt;ofport = u16_to_ofp(ofport);</span><br><span class="line">                        tun-&gt;type = tunnel_type;</span><br><span class="line">                        physical_map_changed = <span class="literal">true</span>;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    tun = xmalloc(<span class="keyword">sizeof</span> *tun);</span><br><span class="line">                    hmap_insert(&amp;tunnels, &amp;tun-&gt;hmap_node,</span><br><span class="line">                                hash_string(chassis_id, <span class="number">0</span>));</span><br><span class="line">                    tun-&gt;chassis_id = chassis_id;</span><br><span class="line">                    tun-&gt;ofport = u16_to_ofp(ofport);</span><br><span class="line">                    tun-&gt;type = tunnel_type;</span><br><span class="line">                    physical_map_changed = <span class="literal">true</span>;</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="keyword">const</span> <span class="keyword">char</span> *iface_id = smap_get(&amp;iface_rec-&gt;external_ids,</span><br><span class="line">                                                <span class="string">"iface-id"</span>);</span><br><span class="line">                <span class="keyword">if</span> (iface_id) &#123;</span><br><span class="line">                    simap_put(&amp;new_localvif_to_ofport, iface_id, ofport);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//清理不存在的tunnel口</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">chassis_tunnel</span> *<span class="title">tun</span>, *<span class="title">tun_next</span>;</span></span><br><span class="line">    HMAP_FOR_EACH_SAFE (tun, tun_next, hmap_node, &amp;tunnels) &#123;</span><br><span class="line">        <span class="keyword">if</span> (!simap_find(&amp;new_tunnel_to_ofport, tun-&gt;chassis_id)) &#123;</span><br><span class="line">            hmap_remove(&amp;tunnels, &amp;tun-&gt;hmap_node);</span><br><span class="line">            physical_map_changed = <span class="literal">true</span>;</span><br><span class="line">            <span class="built_in">free</span>(tun);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//记录下更改或者删除的openflow ports</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">simap_node</span> *<span class="title">vif_name</span>, *<span class="title">vif_name_next</span>;</span></span><br><span class="line">    SIMAP_FOR_EACH_SAFE (vif_name, vif_name_next, &amp;localvif_to_ofport) &#123;</span><br><span class="line">        <span class="keyword">int</span> newport;</span><br><span class="line">        <span class="keyword">if</span> ((newport = simap_get(&amp;new_localvif_to_ofport, vif_name-&gt;name))) &#123;</span><br><span class="line">            <span class="keyword">if</span> (newport != simap_get(&amp;localvif_to_ofport, vif_name-&gt;name)) &#123;</span><br><span class="line">                simap_put(&amp;localvif_to_ofport, vif_name-&gt;name, newport);</span><br><span class="line">                physical_map_changed = <span class="literal">true</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            simap_find_and_delete(&amp;localvif_to_ofport, vif_name-&gt;name);</span><br><span class="line">            physical_map_changed = <span class="literal">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    SIMAP_FOR_EACH (vif_name, &amp;new_localvif_to_ofport) &#123;</span><br><span class="line">        <span class="keyword">if</span> (!simap_get(&amp;localvif_to_ofport, vif_name-&gt;name)) &#123;</span><br><span class="line">            simap_put(&amp;localvif_to_ofport, vif_name-&gt;name,</span><br><span class="line">                      simap_get(&amp;new_localvif_to_ofport, vif_name-&gt;name));</span><br><span class="line">            physical_map_changed = <span class="literal">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (physical_map_changed) &#123;</span><br><span class="line">        <span class="comment">//调用此处触发logical flow table的处理</span></span><br><span class="line">        poll_immediate_wake();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">ofpbuf</span> <span class="title">ofpacts</span>;</span></span><br><span class="line">    ofpbuf_init(&amp;ofpacts, <span class="number">0</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment">//建立表0，建立physical-to-logical的映射</span></span><br><span class="line">    <span class="comment">//建立表32，报文到远端宿主机的tunnel流量</span></span><br><span class="line">    <span class="comment">//建立表65，走完一个逻辑网元到下一个逻辑网元的流表</span></span><br><span class="line">    <span class="keyword">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">sbrec_port_binding</span> *<span class="title">binding</span>;</span></span><br><span class="line">    SBREC_PORT_BINDING_FOR_EACH (binding, ctx-&gt;ovnsb_idl) &#123;</span><br><span class="line">        consider_port_binding(mff_ovn_geneve, ct_zones, lports,</span><br><span class="line">                              local_datapaths, binding, chassis,</span><br><span class="line">                              &amp;ofpacts, flow_table);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//table 32 33处理报文到multicast groups</span></span><br><span class="line">    <span class="keyword">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">sbrec_multicast_group</span> *<span class="title">mc</span>;</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">ofpbuf</span> <span class="title">remote_ofpacts</span>;</span></span><br><span class="line">    ofpbuf_init(&amp;remote_ofpacts, <span class="number">0</span>);</span><br><span class="line">    SBREC_MULTICAST_GROUP_FOR_EACH (mc, ctx-&gt;ovnsb_idl) &#123;</span><br><span class="line">        consider_mc_group(mff_ovn_geneve, ct_zones, local_datapaths, chassis,</span><br><span class="line">                          mc, &amp;ofpacts, &amp;remote_ofpacts, flow_table);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    ofpbuf_uninit(&amp;remote_ofpacts);</span><br><span class="line"></span><br><span class="line">    <span class="comment">//表0 100优先级，处理从tunnel口收到的报文</span></span><br><span class="line">    <span class="comment">//Geneve和STT封装因为包含了ingress和egress的逻辑口</span></span><br><span class="line">    <span class="comment">//我们从封装信息获取MFF_LOG_DATAPATH, MFF_LOG_INPORT, MFF_LOG_OUTPORT</span></span><br><span class="line">    <span class="comment">//重新提交到表33，发送报文到本地vm</span></span><br><span class="line">    <span class="comment">//这里先不处理vxlan的报文</span></span><br><span class="line">    HMAP_FOR_EACH (tun, hmap_node, &amp;tunnels) &#123;</span><br><span class="line">        <span class="class"><span class="keyword">struct</span> <span class="title">match</span> <span class="title">match</span> = <span class="title">MATCH_CATCHALL_INITIALIZER</span>;</span></span><br><span class="line">        match_set_in_port(&amp;match, tun-&gt;ofport);</span><br><span class="line"></span><br><span class="line">        ofpbuf_clear(&amp;ofpacts);</span><br><span class="line">        <span class="keyword">if</span> (tun-&gt;type == GENEVE) &#123;</span><br><span class="line">            put_move(MFF_TUN_ID, <span class="number">0</span>,  MFF_LOG_DATAPATH, <span class="number">0</span>, <span class="number">24</span>, &amp;ofpacts);</span><br><span class="line">            put_move(mff_ovn_geneve, <span class="number">16</span>, MFF_LOG_INPORT, <span class="number">0</span>, <span class="number">15</span>,</span><br><span class="line">                     &amp;ofpacts);</span><br><span class="line">            put_move(mff_ovn_geneve, <span class="number">0</span>, MFF_LOG_OUTPORT, <span class="number">0</span>, <span class="number">16</span>,</span><br><span class="line">                     &amp;ofpacts);</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (tun-&gt;type == STT) &#123;</span><br><span class="line">            put_move(MFF_TUN_ID, <span class="number">40</span>, MFF_LOG_INPORT,   <span class="number">0</span>, <span class="number">15</span>, &amp;ofpacts);</span><br><span class="line">            put_move(MFF_TUN_ID, <span class="number">24</span>, MFF_LOG_OUTPORT,  <span class="number">0</span>, <span class="number">16</span>, &amp;ofpacts);</span><br><span class="line">            put_move(MFF_TUN_ID,  <span class="number">0</span>, MFF_LOG_DATAPATH, <span class="number">0</span>, <span class="number">24</span>, &amp;ofpacts);</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (tun-&gt;type == VXLAN) &#123;</span><br><span class="line">            <span class="keyword">continue</span>;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            OVS_NOT_REACHED();</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        put_resubmit(OFTABLE_LOCAL_OUTPUT, &amp;ofpacts);</span><br><span class="line"></span><br><span class="line">        ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG, <span class="number">100</span>, <span class="number">0</span>, &amp;match,</span><br><span class="line">                        &amp;ofpacts);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//目前只支持VXLAN连接网关，VNI存于MFF_LOG_INPORT</span></span><br><span class="line">    <span class="comment">//然后报文提交到表16，然后确定出口</span></span><br><span class="line">    <span class="comment">//目前测试是跨子网的东西流量不通</span></span><br><span class="line">    HMAP_FOR_EACH (tun, hmap_node, &amp;tunnels) &#123;</span><br><span class="line">        SBREC_PORT_BINDING_FOR_EACH (binding, ctx-&gt;ovnsb_idl) &#123;</span><br><span class="line">            <span class="class"><span class="keyword">struct</span> <span class="title">match</span> <span class="title">match</span> = <span class="title">MATCH_CATCHALL_INITIALIZER</span>;</span></span><br><span class="line"></span><br><span class="line">            match_set_in_port(&amp;match, tun-&gt;ofport);</span><br><span class="line">            match_set_tun_id(&amp;match, htonll(binding-&gt;datapath-&gt;tunnel_key));</span><br><span class="line"></span><br><span class="line">            ofpbuf_clear(&amp;ofpacts);</span><br><span class="line">            put_move(MFF_TUN_ID, <span class="number">0</span>,  MFF_LOG_DATAPATH, <span class="number">0</span>, <span class="number">24</span>, &amp;ofpacts);</span><br><span class="line">            put_load(binding-&gt;tunnel_key, MFF_LOG_INPORT, <span class="number">0</span>, <span class="number">15</span>, &amp;ofpacts);</span><br><span class="line">            put_load(<span class="number">1</span>, MFF_LOG_FLAGS, MLF_RCV_FROM_VXLAN_BIT, <span class="number">1</span>, &amp;ofpacts);</span><br><span class="line">            put_resubmit(OFTABLE_LOG_INGRESS_PIPELINE, &amp;ofpacts);</span><br><span class="line"></span><br><span class="line">            ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG, <span class="number">100</span>, <span class="number">0</span>, &amp;match,</span><br><span class="line">                            &amp;ofpacts);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">     <span class="comment">//表32 150优先级，处理收到的vxlan报文，因为缺乏metadata</span></span><br><span class="line">     <span class="comment">//不发送任何隧道，重新提交到表33</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">match</span> <span class="title">match</span>;</span></span><br><span class="line">    match_init_catchall(&amp;match);</span><br><span class="line">    ofpbuf_clear(&amp;ofpacts);</span><br><span class="line">    match_set_reg_masked(&amp;match, MFF_LOG_FLAGS - MFF_REG0,</span><br><span class="line">                         MLF_RCV_FROM_VXLAN, MLF_RCV_FROM_VXLAN);</span><br><span class="line"></span><br><span class="line">    put_resubmit(OFTABLE_LOCAL_OUTPUT, &amp;ofpacts);</span><br><span class="line">    ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, <span class="number">150</span>, <span class="number">0</span>,</span><br><span class="line">                    &amp;match, &amp;ofpacts);</span><br><span class="line"></span><br><span class="line">    <span class="comment">//表32 0优先级，不是组播或者tunnel到本地出口报文就重新提交到表33</span></span><br><span class="line">    match_init_catchall(&amp;match);</span><br><span class="line">    ofpbuf_clear(&amp;ofpacts);</span><br><span class="line">    put_resubmit(OFTABLE_LOCAL_OUTPUT, &amp;ofpacts);</span><br><span class="line">    ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, <span class="number">0</span>, <span class="number">0</span>, &amp;match, &amp;ofpacts);</span><br><span class="line"></span><br><span class="line">    <span class="comment">//表34 0优先级，不是出ingress口，而是进入egress流程的话，清楚寄存器</span></span><br><span class="line">    match_init_catchall(&amp;match);</span><br><span class="line">    ofpbuf_clear(&amp;ofpacts);</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; MFF_N_LOG_REGS; i++) &#123;</span><br><span class="line">        put_load(<span class="number">0</span>, MFF_REG0 + i, <span class="number">0</span>, <span class="number">32</span>, &amp;ofpacts);</span><br><span class="line">    &#125;</span><br><span class="line">    put_resubmit(OFTABLE_LOG_EGRESS_PIPELINE, &amp;ofpacts);</span><br><span class="line">    ofctrl_add_flow(flow_table, OFTABLE_CHECK_LOOPBACK, <span class="number">0</span>, <span class="number">0</span>, &amp;match,</span><br><span class="line">                    &amp;ofpacts);</span><br><span class="line"></span><br><span class="line">    <span class="comment">//表64 0优先级，没有MLF_ALLOW_LOOPBACK标志的报文</span></span><br><span class="line">    <span class="comment">//重新提交到表65进行logical-to-physical的转换</span></span><br><span class="line">    match_init_catchall(&amp;match);</span><br><span class="line">    ofpbuf_clear(&amp;ofpacts);</span><br><span class="line">    put_resubmit(OFTABLE_LOG_TO_PHY, &amp;ofpacts);</span><br><span class="line">    ofctrl_add_flow(flow_table, OFTABLE_SAVE_INPORT, <span class="number">0</span>, <span class="number">0</span>, &amp;match, &amp;ofpacts);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">static</span> <span class="keyword">void</span></span><br><span class="line">consider_port_binding(<span class="keyword">enum</span> mf_field_id mff_ovn_geneve,</span><br><span class="line">                      <span class="keyword">const</span> struct simap *ct_zones,</span><br><span class="line">                      <span class="keyword">const</span> struct lport_index *lports,</span><br><span class="line">                      struct hmap *local_datapaths,</span><br><span class="line">                      <span class="keyword">const</span> struct sbrec_port_binding *binding,</span><br><span class="line">                      <span class="keyword">const</span> struct sbrec_chassis *chassis,</span><br><span class="line">                      struct ofpbuf *ofpacts_p,</span><br><span class="line">                      struct hmap *flow_table)</span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">uint32_t</span> dp_key = binding-&gt;datapath-&gt;tunnel_key;</span><br><span class="line">    <span class="keyword">uint32_t</span> port_key = binding-&gt;tunnel_key;</span><br><span class="line">    <span class="keyword">if</span> (!get_local_datapath(local_datapaths, dp_key)) &#123;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">match</span> <span class="title">match</span>;</span></span><br><span class="line">    <span class="keyword">if</span> (!<span class="built_in">strcmp</span>(binding-&gt;type, <span class="string">"patch"</span>)</span><br><span class="line">        || (!<span class="built_in">strcmp</span>(binding-&gt;type, <span class="string">"l3gateway"</span>)</span><br><span class="line">            &amp;&amp; binding-&gt;chassis == chassis)) &#123;</span><br><span class="line">        <span class="keyword">const</span> <span class="keyword">char</span> *peer_name = smap_get(&amp;binding-&gt;options, <span class="string">"peer"</span>);</span><br><span class="line">        <span class="keyword">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">sbrec_port_binding</span> *<span class="title">peer</span> = <span class="title">lport_lookup_by_name</span>(</span></span><br><span class="line"><span class="class">            <span class="title">lports</span>, <span class="title">peer_name</span>);</span></span><br><span class="line">        <span class="keyword">const</span> <span class="keyword">char</span> *peer_peer_name = smap_get(&amp;peer-&gt;options, <span class="string">"peer"</span>);</span><br><span class="line">        <span class="class"><span class="keyword">struct</span> <span class="title">zone_ids</span> <span class="title">binding_zones</span> = <span class="title">get_zone_ids</span>(<span class="title">binding</span>, <span class="title">ct_zones</span>);</span></span><br><span class="line">        <span class="comment">//表33 100优先级，每个flow对应一个端口，resubmit到表34</span></span><br><span class="line">        <span class="comment">//表34 100优先级，logical入口和出口一样的报文丢弃</span></span><br><span class="line">        <span class="comment">//表64 100优先级，入端口修改为0，resubmit到表65</span></span><br><span class="line">        put_local_common_flows(dp_key, port_key, <span class="literal">false</span>, &amp;binding_zones,</span><br><span class="line">                               ofpacts_p, flow_table);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//表65 100优先级，清空寄存器，resubmit到表16</span></span><br><span class="line">        <span class="comment">//表示过完了当前的一个网元，要进入下一个网元</span></span><br><span class="line">        match_init_catchall(&amp;match);</span><br><span class="line">        ofpbuf_clear(ofpacts_p);</span><br><span class="line">        match_set_metadata(&amp;match, htonll(dp_key));</span><br><span class="line">        match_set_reg(&amp;match, MFF_LOG_OUTPORT - MFF_REG0, port_key);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">size_t</span> clone_ofs = ofpacts_p-&gt;size;</span><br><span class="line">        <span class="class"><span class="keyword">struct</span> <span class="title">ofpact_nest</span> *<span class="title">clone</span> = <span class="title">ofpact_put_CLONE</span>(<span class="title">ofpacts_p</span>);</span></span><br><span class="line">        ofpact_put_CT_CLEAR(ofpacts_p);</span><br><span class="line">        put_load(<span class="number">0</span>, MFF_LOG_DNAT_ZONE, <span class="number">0</span>, <span class="number">32</span>, ofpacts_p);</span><br><span class="line">        put_load(<span class="number">0</span>, MFF_LOG_SNAT_ZONE, <span class="number">0</span>, <span class="number">32</span>, ofpacts_p);</span><br><span class="line">        put_load(<span class="number">0</span>, MFF_LOG_CT_ZONE, <span class="number">0</span>, <span class="number">32</span>, ofpacts_p);</span><br><span class="line">        <span class="class"><span class="keyword">struct</span> <span class="title">zone_ids</span> <span class="title">peer_zones</span> = <span class="title">get_zone_ids</span>(<span class="title">peer</span>, <span class="title">ct_zones</span>);</span></span><br><span class="line">        load_logical_ingress_metadata(peer, &amp;peer_zones, ofpacts_p);</span><br><span class="line">        put_load(<span class="number">0</span>, MFF_LOG_FLAGS, <span class="number">0</span>, <span class="number">32</span>, ofpacts_p);</span><br><span class="line">        put_load(<span class="number">0</span>, MFF_LOG_OUTPORT, <span class="number">0</span>, <span class="number">32</span>, ofpacts_p);</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; MFF_N_LOG_REGS; i++) &#123;</span><br><span class="line">            put_load(<span class="number">0</span>, MFF_LOG_REG0 + i, <span class="number">0</span>, <span class="number">32</span>, ofpacts_p);</span><br><span class="line">        &#125;</span><br><span class="line">        put_load(<span class="number">0</span>, MFF_IN_PORT, <span class="number">0</span>, <span class="number">16</span>, ofpacts_p);</span><br><span class="line">        put_resubmit(OFTABLE_LOG_INGRESS_PIPELINE, ofpacts_p);</span><br><span class="line">        clone = ofpbuf_at_assert(ofpacts_p, clone_ofs, <span class="keyword">sizeof</span> *clone);</span><br><span class="line">        ofpacts_p-&gt;header = clone;</span><br><span class="line">        ofpact_finish_CLONE(ofpacts_p, &amp;clone);</span><br><span class="line"></span><br><span class="line">        ofctrl_add_flow(flow_table, OFTABLE_LOG_TO_PHY, <span class="number">100</span>, <span class="number">0</span>,</span><br><span class="line">                        &amp;match, ofpacts_p);</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (!<span class="built_in">strcmp</span>(binding-&gt;type, <span class="string">"chassisredirect"</span>)</span><br><span class="line">        &amp;&amp; binding-&gt;chassis == chassis) &#123;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//表33 100优先级，每个flow匹配一个逻辑出口到reg15，resubmit到表34</span></span><br><span class="line">        <span class="comment">//如果端口类型是chassisredirect，则修改逻辑出口</span></span><br><span class="line">        match_init_catchall(&amp;match);</span><br><span class="line">        ofpbuf_clear(ofpacts_p);</span><br><span class="line">        match_set_metadata(&amp;match, htonll(dp_key));</span><br><span class="line">        match_set_reg(&amp;match, MFF_LOG_OUTPORT - MFF_REG0, port_key);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">const</span> <span class="keyword">char</span> *distributed_port = smap_get(&amp;binding-&gt;options,</span><br><span class="line">                                                <span class="string">"distributed-port"</span>);</span><br><span class="line">        <span class="keyword">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">sbrec_port_binding</span> *<span class="title">distributed_binding</span></span></span><br><span class="line"><span class="class">            = <span class="title">lport_lookup_by_name</span>(<span class="title">lports</span>, <span class="title">distributed_port</span>);</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (!distributed_binding) &#123;</span><br><span class="line">            <span class="keyword">static</span> <span class="class"><span class="keyword">struct</span> <span class="title">vlog_rate_limit</span> <span class="title">rl</span> = <span class="title">VLOG_RATE_LIMIT_INIT</span>(1, 1);</span></span><br><span class="line">            VLOG_WARN_RL(&amp;rl, <span class="string">"No port binding record for distributed "</span></span><br><span class="line">                         <span class="string">"port %s referred by chassisredirect port %s"</span>,</span><br><span class="line">                         distributed_port,</span><br><span class="line">                         binding-&gt;logical_port);</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (binding-&gt;datapath !=</span><br><span class="line">                   distributed_binding-&gt;datapath) &#123;</span><br><span class="line">            <span class="keyword">static</span> struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(<span class="number">1</span>, <span class="number">1</span>);</span><br><span class="line">            VLOG_WARN_RL(&amp;rl,</span><br><span class="line">                         <span class="string">"chassisredirect port %s refers to "</span></span><br><span class="line">                         <span class="string">"distributed port %s in wrong datapath"</span>,</span><br><span class="line">                         binding-&gt;logical_port,</span><br><span class="line">                         distributed_port);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            put_load(distributed_binding-&gt;tunnel_key,</span><br><span class="line">                     MFF_LOG_OUTPORT, <span class="number">0</span>, <span class="number">32</span>, ofpacts_p);</span><br><span class="line"></span><br><span class="line">            <span class="class"><span class="keyword">struct</span> <span class="title">zone_ids</span> <span class="title">zone_ids</span> = <span class="title">get_zone_ids</span>(<span class="title">distributed_binding</span>,</span></span><br><span class="line"><span class="class">                                                    <span class="title">ct_zones</span>);</span></span><br><span class="line">            <span class="keyword">if</span> (zone_ids.ct) &#123;</span><br><span class="line">                put_load(zone_ids.ct, MFF_LOG_CT_ZONE, <span class="number">0</span>, <span class="number">32</span>, ofpacts_p);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (zone_ids.dnat) &#123;</span><br><span class="line">                put_load(zone_ids.dnat, MFF_LOG_DNAT_ZONE, <span class="number">0</span>, <span class="number">32</span>, ofpacts_p);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (zone_ids.snat) &#123;</span><br><span class="line">                put_load(zone_ids.snat, MFF_LOG_SNAT_ZONE, <span class="number">0</span>, <span class="number">32</span>, ofpacts_p);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            put_resubmit(OFTABLE_CHECK_LOOPBACK, ofpacts_p);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        ofctrl_add_flow(flow_table, OFTABLE_LOCAL_OUTPUT, <span class="number">100</span>, <span class="number">0</span>,</span><br><span class="line">                        &amp;match, ofpacts_p);</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//根据逻辑端口查找ofport</span></span><br><span class="line">    <span class="comment">//如果端口是VIF，那么ofport是VIF，tun为NULL</span></span><br><span class="line">    <span class="comment">//如果端口是远程的chassis，那么ofport是tunnel，tun的id是对端的chassis tun_key</span></span><br><span class="line">    <span class="keyword">int</span> tag = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">bool</span> nested_container = <span class="literal">false</span>;</span><br><span class="line">    <span class="keyword">ofp_port_t</span> ofport;</span><br><span class="line">    <span class="keyword">bool</span> is_remote = <span class="literal">false</span>;</span><br><span class="line">    <span class="keyword">if</span> (binding-&gt;parent_port &amp;&amp; *binding-&gt;parent_port) &#123;</span><br><span class="line">        ofport = u16_to_ofp(simap_get(&amp;localvif_to_ofport,</span><br><span class="line">                                      binding-&gt;parent_port));</span><br><span class="line">        <span class="keyword">if</span> (ofport) &#123;</span><br><span class="line">            tag = *binding-&gt;tag;</span><br><span class="line">            nested_container = <span class="literal">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        ofport = u16_to_ofp(simap_get(&amp;localvif_to_ofport,</span><br><span class="line">                                      binding-&gt;logical_port));</span><br><span class="line">        <span class="keyword">if</span> ((!<span class="built_in">strcmp</span>(binding-&gt;type, <span class="string">"localnet"</span>)</span><br><span class="line">            || !<span class="built_in">strcmp</span>(binding-&gt;type, <span class="string">"l2gateway"</span>))</span><br><span class="line">            &amp;&amp; ofport &amp;&amp; binding-&gt;tag) &#123;</span><br><span class="line">            tag = *binding-&gt;tag;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">chassis_tunnel</span> *<span class="title">tun</span> = <span class="title">NULL</span>;</span></span><br><span class="line">    <span class="keyword">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">sbrec_port_binding</span> *<span class="title">localnet_port</span> =</span></span><br><span class="line"><span class="class">        <span class="title">get_localnet_port</span>(<span class="title">local_datapaths</span>, <span class="title">dp_key</span>);</span></span><br><span class="line">    <span class="keyword">if</span> (!ofport) &#123;</span><br><span class="line">        is_remote = <span class="literal">true</span>;</span><br><span class="line">        <span class="keyword">if</span> (!binding-&gt;chassis) &#123;</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (localnet_port) &#123;</span><br><span class="line">            ofport = u16_to_ofp(simap_get(&amp;localvif_to_ofport,</span><br><span class="line">                                          localnet_port-&gt;logical_port));</span><br><span class="line">            <span class="keyword">if</span> (!ofport) &#123;</span><br><span class="line">                <span class="keyword">return</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            tun = chassis_tunnel_find(binding-&gt;chassis-&gt;name);</span><br><span class="line">            <span class="keyword">if</span> (!tun) &#123;</span><br><span class="line">                <span class="keyword">return</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            ofport = tun-&gt;ofport;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (!is_remote) &#123;</span><br><span class="line">        <span class="class"><span class="keyword">struct</span> <span class="title">zone_ids</span> <span class="title">zone_ids</span> = <span class="title">get_zone_ids</span>(<span class="title">binding</span>, <span class="title">ct_zones</span>);</span></span><br><span class="line">        put_local_common_flows(dp_key, port_key, nested_container, &amp;zone_ids,</span><br><span class="line">                               ofpacts_p, flow_table);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//表0 100和150优先级</span></span><br><span class="line">        <span class="comment">//150优先级是标记的流量，可能是VM中的容器或者local network的vlan情况下</span></span><br><span class="line">        <span class="comment">//会匹配标记和剥去标记</span></span><br><span class="line">        <span class="comment">//100优先级是vm的流量或者没有标记的本地网络</span></span><br><span class="line">        <span class="comment">//这两种流量都需要设置逻辑入端口，逻辑datapath和resubmit到表16</span></span><br><span class="line">        ofpbuf_clear(ofpacts_p);</span><br><span class="line">        match_init_catchall(&amp;match);</span><br><span class="line">        match_set_in_port(&amp;match, ofport);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (tag || !<span class="built_in">strcmp</span>(binding-&gt;type, <span class="string">"localnet"</span>)</span><br><span class="line">            || !<span class="built_in">strcmp</span>(binding-&gt;type, <span class="string">"l2gateway"</span>)) &#123;</span><br><span class="line">            match_set_dl_vlan(&amp;match, htons(tag));</span><br><span class="line">            <span class="keyword">if</span> (nested_container) &#123;</span><br><span class="line">                put_load(MLF_ALLOW_LOOPBACK, MFF_LOG_FLAGS, <span class="number">0</span>, <span class="number">1</span>, ofpacts_p);</span><br><span class="line">            &#125;</span><br><span class="line">            ofpact_put_STRIP_VLAN(ofpacts_p);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">uint32_t</span> ofpacts_orig_size = ofpacts_p-&gt;size;</span><br><span class="line"></span><br><span class="line">        load_logical_ingress_metadata(binding, &amp;zone_ids, ofpacts_p);</span><br><span class="line"></span><br><span class="line">        put_resubmit(OFTABLE_LOG_INGRESS_PIPELINE, ofpacts_p);</span><br><span class="line">        ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG,</span><br><span class="line">                        tag ? <span class="number">150</span> : <span class="number">100</span>, <span class="number">0</span>, &amp;match, ofpacts_p);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (!tag &amp;&amp; (!<span class="built_in">strcmp</span>(binding-&gt;type, <span class="string">"localnet"</span>)</span><br><span class="line">                     || !<span class="built_in">strcmp</span>(binding-&gt;type, <span class="string">"l2gateway"</span>))) &#123;</span><br><span class="line"></span><br><span class="line">            ofpbuf_pull(ofpacts_p, ofpacts_orig_size);</span><br><span class="line">            match_set_dl_tci_masked(&amp;match, <span class="number">0</span>, htons(VLAN_CFI));</span><br><span class="line">            ofctrl_add_flow(flow_table, <span class="number">0</span>, <span class="number">100</span>, <span class="number">0</span>, &amp;match, ofpacts_p);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//表65 100优先级，转发报文到本地的vif</span></span><br><span class="line">        match_init_catchall(&amp;match);</span><br><span class="line">        ofpbuf_clear(ofpacts_p);</span><br><span class="line">        match_set_metadata(&amp;match, htonll(dp_key));</span><br><span class="line">        match_set_reg(&amp;match, MFF_LOG_OUTPORT - MFF_REG0, port_key);</span><br><span class="line">        <span class="keyword">if</span> (tag) &#123;</span><br><span class="line">            <span class="class"><span class="keyword">struct</span> <span class="title">ofpact_vlan_vid</span> *<span class="title">vlan_vid</span>;</span></span><br><span class="line">            vlan_vid = ofpact_put_SET_VLAN_VID(ofpacts_p);</span><br><span class="line">            vlan_vid-&gt;vlan_vid = tag;</span><br><span class="line">            vlan_vid-&gt;push_vlan_if_needed = <span class="literal">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        ofpact_put_OUTPUT(ofpacts_p)-&gt;port = ofport;</span><br><span class="line">        <span class="keyword">if</span> (tag) &#123;</span><br><span class="line">            ofpact_put_STRIP_VLAN(ofpacts_p);</span><br><span class="line">        &#125;</span><br><span class="line">        ofctrl_add_flow(flow_table, OFTABLE_LOG_TO_PHY, <span class="number">100</span>, <span class="number">0</span>,</span><br><span class="line">                        &amp;match, ofpacts_p);</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (!tun) &#123;</span><br><span class="line">        <span class="comment">//表33 100优先级，完成交换到localnet端口，每个flow匹配一个逻辑出口</span></span><br><span class="line">        <span class="comment">//切换出口到localnet口和resubmit到同样的表，即表33</span></span><br><span class="line">        match_init_catchall(&amp;match);</span><br><span class="line">        ofpbuf_clear(ofpacts_p);</span><br><span class="line"></span><br><span class="line">        match_set_metadata(&amp;match, htonll(dp_key));</span><br><span class="line">        match_set_reg(&amp;match, MFF_LOG_OUTPORT - MFF_REG0, port_key);</span><br><span class="line"></span><br><span class="line">        put_load(localnet_port-&gt;tunnel_key, MFF_LOG_OUTPORT, <span class="number">0</span>, <span class="number">32</span>, ofpacts_p);</span><br><span class="line"></span><br><span class="line">        put_resubmit(OFTABLE_LOCAL_OUTPUT, ofpacts_p);</span><br><span class="line">        ofctrl_add_flow(flow_table, OFTABLE_LOCAL_OUTPUT, <span class="number">100</span>, <span class="number">0</span>,</span><br><span class="line">                        &amp;match, ofpacts_p);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="comment">//表32 100优先级，将流量发送到远端设备，每一条flow匹配一个出口</span></span><br><span class="line">        <span class="comment">//封装报文到远端</span></span><br><span class="line">        match_init_catchall(&amp;match);</span><br><span class="line">        ofpbuf_clear(ofpacts_p);</span><br><span class="line"></span><br><span class="line">        match_set_metadata(&amp;match, htonll(dp_key));</span><br><span class="line">        match_set_reg(&amp;match, MFF_LOG_OUTPORT - MFF_REG0, port_key);</span><br><span class="line"></span><br><span class="line">        put_encapsulation(mff_ovn_geneve, tun, binding-&gt;datapath,</span><br><span class="line">                          port_key, ofpacts_p);</span><br><span class="line"></span><br><span class="line">        ofpact_put_OUTPUT(ofpacts_p)-&gt;port = ofport;</span><br><span class="line">        ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, <span class="number">100</span>, <span class="number">0</span>,</span><br><span class="line">                        &amp;match, ofpacts_p);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div><div></div><footer class="post-footer"><div class="post-nav"><div class="post-nav-next post-nav-item"><a href="/2017/03/05/SDN/OVS/2017-03-05-flow-translate/" rel="next" title="OpenvSwitch 流表转换"><i class="fa fa-chevron-left"></i> OpenvSwitch 流表转换</a></div><div class="post-nav-prev post-nav-item"> <a href="/2017/03/22/SDN/OVS/2017-03-22-traps/" rel="prev" title="OVS-DPDK 我们遇到的坑">OVS-DPDK 我们遇到的坑<i class="fa fa-chevron-right"></i></a></div></div></footer></div></article><div class="post-copyright"><p><span>注意:</span>所有文章非特别说明皆为原创。为保证信息与源同步，转载时请务必注明文章出处！谢谢合作 :-)</p><p> <span>原始链接:</span><a class="post-url" href="/2017/03/11/SDN/OVN/2017-03-11-ovn-controller/" title="OVN controller工作">http://zhaozhanxu.com/2017/03/11/SDN/OVN/2017-03-11-ovn-controller/</a><span class="copy-path" data-clipboard-text="原文: http://zhaozhanxu.com/2017/03/11/SDN/OVN/2017-03-11-ovn-controller/　　作者: 赵占旭" title="点击复制文章链接"><i class="fa fa-clipboard"></i></span><script src="/js/clipboard.min.js"></script><script>var clipboard=new Clipboard(".copy-path")</script></p><p> <span>许可协议:</span><i class="fa fa-creative-commons"></i> <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/cn" title="中国大陆 (CC BY-NC-SA 4.0 CN)" target="_blank">"署名-非商用-相同方式共享 4.0"</a> 转载请保留原文链接及作者。</p></div></div></div><div class="comments" id="comments"></div></div><div class="sidebar-toggle"><div class="sidebar-toggle-line-wrap"><span class="sidebar-toggle-line sidebar-toggle-line-first"></span><span class="sidebar-toggle-line sidebar-toggle-line-middle"></span><span class="sidebar-toggle-line sidebar-toggle-line-last"></span></div></div><aside id="sidebar" class="sidebar"><div class="sidebar-inner"><section class="site-overview sidebar-panel sidebar-panel-active"><div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person"> <a href="/about"><img class="site-author-image" itemprop="image" src="/images/public/me.jpg" alt="赵占旭"><p class="site-author-name" itemprop="name">赵占旭</p><p class="site-description motion-element" itemprop="description"></p></a></div><nav class="site-state motion-element"><div class="site-state-item site-state-posts"> <a href="/archives"><span class="site-state-item-count">61</span> <span class="site-state-item-name">posts</span></a></div><div class="site-state-item site-state-categories"> <a href="/categories"><span class="site-state-item-count">7</span> <span class="site-state-item-name">categories</span></a></div><div class="site-state-item site-state-tags"> <a href="/tags"><span class="site-state-item-count">14</span> <span class="site-state-item-name">tags</span></a></div></nav><div class="feed-link motion-element"><a href="/atom.xml" rel="alternate"><i class="fa fa-rss"></i> RSS</a></div><div class="links-of-author motion-element"><span class="links-of-author-item"><a href="mailto:zhaozhanxu@163.com" target="_blank" title="Mail"><i class="fa fa-fw fa-envelope"></i> Mail</a></span><span class="links-of-author-item"><a href="https://github.com/zhaozhanxu" target="_blank" title="GitHub"><i class="fa fa-fw fa-github"></i> GitHub</a></span><span class="links-of-author-item"><a href="https://www.linkedin.com/in/zhaozhanxu" target="_blank" title="LinkedIn"><i class="fa fa-fw fa-linkedin"></i> LinkedIn</a></span><span class="links-of-author-item"><a href="https://twitter.com/zhaozhanxu" target="_blank" title="Twitter"><i class="fa fa-fw fa-twitter"></i> Twitter</a></span><span class="links-of-author-item"><a href="/about/" target="_blank" title="Wechat"><i class="fa fa-fw fa-wechat"></i> Wechat</a></span><span class="links-of-author-item"><a href="/about/" target="_blank" title="QQ"><i class="fa fa-fw fa-qq"></i> QQ</a></span></div><div class="links-of-blogroll motion-element links-of-blogroll-inline"><div class="links-of-blogroll-title"><i class="fa fa-fw fa-address-book"></i> 基情链接</div><ul class="links-of-blogroll-list"><li class="links-of-blogroll-item"> <a href="http://blog.csdn.net/jqh9804" title="呆子辉" target="_blank">呆子辉</a></li></ul></div></section></div></aside></div></main><footer id="footer" class="footer"><div class="footer-inner"><div class="copyright"> &copy; 2016 - <span itemprop="copyrightYear">2017</span><span class="with-love"><i class="fa fa-heart"></i></span> <span class="author" itemprop="copyrightHolder">赵占旭</span></div><div class="powered-by"> Powered by <a class="theme-link" href="https://hexo.io">Hexo</a></div><div class="theme-info"> Theme - <a class="theme-link" href="https://github.com/iissnan/hexo-theme-next">NexT</a></div><div class="busuanzi-count"><script async src="https://dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js"></script><span class="site-uv"><i class="fa fa-user"></i><span class="busuanzi-value" id="busuanzi_value_site_uv"></span></span><span class="site-pv"><i class="fa fa-eye"></i><span class="busuanzi-value" id="busuanzi_value_page_pv"></span></span></div></div></footer><div class="back-to-top"><i class="fa fa-arrow-up"></i></div></div><script type="text/javascript">"[object Function]"!==Object.prototype.toString.call(window.Promise)&&(window.Promise=null)</script><script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script><script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script><script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script><script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script><script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script><script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script><script type="text/javascript" src="/lib/canvas-nest/canvas-nest.min.js"></script><script type="text/javascript" src="/js/src/utils.js?v=5.1.0"></script><script type="text/javascript" src="/js/src/motion.js?v=5.1.0"></script><script type="text/javascript" src="/js/src/affix.js?v=5.1.0"></script><script type="text/javascript" src="/js/src/schemes/pisces.js?v=5.1.0"></script><script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.0"></script><script type="text/javascript" src="/js/src/post-details.js?v=5.1.0"></script><script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.0"></script><script type="text/javascript">function proceedsearch(){$("body").append('<div class="popoverlay">').css("overflow","hidden"),$(".popup").toggle()}var isfetched=!1,search_path="search.xml";0==search_path.length&&(search_path="search.xml");var path="/"+search_path,searchFunc=function(e,t,a){"use strict";$.ajax({url:e,dataType:"xml",async:!0,success:function(e){isfetched=!0,$(".popup").detach().appendTo(".header-inner");var r=$("entry",e).map(function(){return{title:$("title",this).text(),content:$("content",this).text(),url:$("url",this).text()}}).get(),c=document.getElementById(t),n=document.getElementById(a);c.addEventListener("input",function(){var e=0,t='<ul class="search-result-list">',a=this.value.trim().toLowerCase().split(/[\s\-]+/);n.innerHTML="",this.value.trim().length>1&&r.forEach(function(r){var c=!1,n=r.title.trim().toLowerCase(),s=r.content.trim().replace(/<[^>]+>/g,"").toLowerCase(),o=decodeURIComponent(r.url),i=-1,l=-1,p=-1;if(""!=n&&a.forEach(function(e,t){i=n.indexOf(e),l=s.indexOf(e),(i>=0||l>=0)&&(c=!0,0==t&&(p=l))}),c){e+=1,t+="<li><a href='"+o+"' class='search-result-title'>"+n+"</a>";var h=r.content.trim().replace(/<[^>]+>/g,"");if(p>=0){var u=p-20,d=p+80;u<0&&(u=0),0==u&&(d=50),d>h.length&&(d=h.length);var f=h.substring(u,d);a.forEach(function(e){var t=new RegExp(e,"gi");f=f.replace(t,'<b class="search-keyword">'+e+"</b>")}),t+='<p class="search-result">'+f+"...</p>"}t+="</li>"}}),t+="</ul>",0==e&&(t='<div id="no-result"><i class="fa fa-frown-o fa-5x" /></div>'),""==a&&(t='<div id="no-result"><i class="fa fa-search fa-5x" /></div>'),n.innerHTML=t}),proceedsearch()}})};$(".popup-trigger").click(function(e){e.stopPropagation(),0==isfetched?searchFunc(path,"local-search-input","local-search-result"):proceedsearch()}),$(".popup-btn-close").click(function(e){$(".popup").hide(),$(".popoverlay").remove(),$("body").css("overflow","")}),$(".popup").click(function(e){e.stopPropagation()})</script><script>!function(){var t=document.createElement("script"),e=window.location.protocol.split(":")[0];t.src="https"===e?"https://zz.bdstatic.com/linksubmit/push.js":"http://push.zhanzhang.baidu.com/push.js";var s=document.getElementsByTagName("script")[0];s.parentNode.insertBefore(t,s)}()</script></body></html>